package com.zzh.partnersys.common.util;

import com.zzh.partnersys.common.exception.BusinessException;
import com.zzh.partnersys.common.exception.ResultCodeEnum;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;

import static com.zzh.partnersys.common.constant.redis.UserConstant.USER_LOGIN_STATE;

/**
 * Session工具类
 * 用于从HttpServletRequest的session中获取用户信息
 * 适用于微服务架构，session存储在Redis中，所有服务共享
 *
 * @author zzh
 */
@Slf4j
public class SessionUtils {

    /**
     * 从session中获取当前登录用户对象
     * 注意：返回的是Object类型，需要调用方自己转换为具体的UserDO类型
     *
     * @param request HttpServletRequest
     * @return 用户对象，如果未登录返回null
     */
    public static Object getCurrentUser(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        HttpSession session = request.getSession(false);
        if (session == null) {
            return null;
        }
        return session.getAttribute(USER_LOGIN_STATE);
    }

    /**
     * 从session中获取当前登录用户对象，如果未登录则抛出异常
     *
     * @param request HttpServletRequest
     * @return 用户对象
     * @throws BusinessException 如果未登录
     */
    public static Object getCurrentUserOrThrow(HttpServletRequest request) {
        Object user = getCurrentUser(request);
        if (user == null) {
            throw new BusinessException(ResultCodeEnum.LOGIN_AUTH);
        }
        return user;
    }

    /**
     * 从session中获取当前登录用户的ID
     * 使用反射获取用户对象的getId()方法
     *
     * @param request HttpServletRequest
     * @return 用户ID，如果未登录返回null
     */
    public static Long getCurrentUserId(HttpServletRequest request) {
        Object user = getCurrentUser(request);
        if (user == null) {
            return null;
        }
        try {
            // 使用反射获取 id 字段
            Object id = user.getClass().getMethod("getId").invoke(user);
            return id != null ? Long.valueOf(id.toString()) : null;
        } catch (Exception e) {
            log.error("获取用户ID失败", e);
            return null;
        }
    }

    /**
     * 从session中获取当前登录用户的ID，如果未登录则抛出异常
     *
     * @param request HttpServletRequest
     * @return 用户ID
     * @throws BusinessException 如果未登录
     */
    public static Long getCurrentUserIdOrThrow(HttpServletRequest request) {
        Long userId = getCurrentUserId(request);
        if (userId == null) {
            throw new BusinessException(ResultCodeEnum.LOGIN_AUTH);
        }
        return userId;
    }

    /**
     * 从session中获取当前登录用户的角色
     * 使用反射获取用户对象的getUserRole()方法
     *
     * @param request HttpServletRequest
     * @return 用户角色，如果未登录返回null
     */
    public static Integer getCurrentUserRole(HttpServletRequest request) {
        Object user = getCurrentUser(request);
        if (user == null) {
            return null;
        }
        try {
            Object role = user.getClass().getMethod("getUserRole").invoke(user);
            return role != null ? Integer.valueOf(role.toString()) : null;
        } catch (Exception e) {
            log.error("获取用户角色失败", e);
            return null;
        }
    }

    /**
     * 判断当前用户是否已登录
     *
     * @param request HttpServletRequest
     * @return true表示已登录，false表示未登录
     */
    public static boolean isLogin(HttpServletRequest request) {
        return getCurrentUser(request) != null;
    }

    /**
     * 判断当前用户是否为管理员
     *
     * @param request HttpServletRequest
     * @return true表示是管理员，false表示不是管理员或未登录
     */
    public static boolean isAdmin(HttpServletRequest request) {
        Integer role = getCurrentUserRole(request);
        return role != null && role == 1; // 1表示管理员
    }

    /**
     * 从session中移除用户登录信息（用于登出）
     *
     * @param request HttpServletRequest
     */
    public static void removeUser(HttpServletRequest request) {
        if (request == null) {
            return;
        }
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.removeAttribute(USER_LOGIN_STATE);
        }
    }

    /**
     * 设置用户登录信息到session
     *
     * @param request HttpServletRequest
     * @param user 用户对象
     */
    public static void setUser(HttpServletRequest request, Object user) {
        if (request == null) {
            return;
        }
        HttpSession session = request.getSession(true);
        session.setAttribute(USER_LOGIN_STATE, user);
    }
}

